<script>
import Header from "../../components/HeaderVue.vue";
import {
  CirclePlusFilled,
  Picture,
  Position,
  Setting,
  ChatDotRound,
  Upload,
  User,
  OfficeBuilding, Tickets, Iphone, Document, DocumentCopy, Mic
} from "@element-plus/icons-vue";
import {nextTick, onMounted, reactive, ref, watch} from "vue";
import {
  clearChatHistory,
  generateMemory,
  getAgentInfo,
  getAiDrawPic,
  getPlayerInfoList, saveAgent,
  savePlayer,
  selectPlayer
} from "../../../api/ai/studentChatAIApi.js";
import {ElLoading, ElMessage, ElNotification} from "element-plus";
import {XfVoiceDictation} from "@muguilin/xf-voice-dictation";
import hljs from "highlight.js";
import 'highlight.js/styles/docco.css'
import {getBase64LinkByUID} from "../../../api/toolbar/ToolBar.js";
import {fetchEventSource} from "@microsoft/fetch-event-source";

export default {
  name: 'StudentChatAI',
  computed: {
    Mic() {
      return Mic
    },
    DocumentCopy() {
      return DocumentCopy
    },
    User() {
      return User
    },
    Upload() {
      return Upload
    },
    ChatDotRound() {
      return ChatDotRound
    },
    Picture() {
      return Picture
    },
    Position() {
      return Position
    },
    CirclePlusFilled() {
      return CirclePlusFilled
    },
    Setting() {
      return Setting
    },
  },
  components: {Document, User, Iphone, Tickets, OfficeBuilding, Header},
  setup()
  {
    const talkTitle = [
      '阅书万卷，我是你的知识宝典',
      '跨界协作，我是你的智能体',
      '一触即发，我是你的灵感引擎',
      '一问即答，我是你的文档专家',
      '一语成诗，我是你的文学大师',
      '一拍即合，我是你的创意伙伴',
    ]
    // 计算添加了几个 新的对话
    // 角色模拟模式下对话框是否显示
    let dialogTableVisible = ref(false);
    // 角色模拟下的导航栏
    let dialogTab = ref('0');
    // 用户询问的问题
    let userQuestion = ref('');
    // 当前用户创建的所有玩家
    let playerList = ref([]);
    // 当前用户正在使用的玩家
    let nowPlayer = ref({});
    // 当前正在使用的人格的信息
    let nowAgent = ref({});
    // 当前模式文字描述
    let modeText = ref('聊天模式');
    // 图片理解模式下上传的图片的base64链接的UID
    let nowFileLinkUID = ref('');
    // 文档问答模式下上传的文件的文件id
    let nowFileId = ref('');
    // 滚动条实例
    const scrollbarRef = ref();
    // 计数器内部实例
    const innerRef = ref();
    // elmentUI 加载变量
    let loading = ref();
    // 添加描述场景表单
    let languageSceneForm = ref({
      agentId: '',
      description: '',
      example: '',
      playerInvolved: '',
      agentInvolved: '',
    });
    // 创建玩家信息表单
    let playerForm = reactive({
      playerName: '',
      playerType: '',
      description: '',
      senderIdentity: '',
    });
    // 创建人格表单
    let agentForm = reactive({
      playerId: '',
      agentName: '',
      agentType: '',
      description: '',
      identity: '',
      personalityDescription: '',
      hobby: '',
      keyPersonality: '',
      mission: '',
    })
    // ai当前的模式
    let mode = ref(0);
    // 聊天内容
    let chatContent = reactive([
      {
        user: "AI",
        content: "你好，有什么可以帮助你的吗？",
        time: new Date().toString()
      },
    ]);
    let loadingMessage = '';
    /*---------------方法----------------*/
    async function setScrollToBottom() {
      // 注意：需要通过 nextTick 以等待 DOM 更新完成
      await nextTick()
      const max = innerRef.value.clientHeight
      scrollbarRef.value.setScrollTop(max)
    }
    // 点击按钮后获取数据
    function getResult() {
      chatContent.push({
        user: "user",
        content: userQuestion.value,
        time: new Date().toString()
      })
      setScrollToBottom()
      // 根据不同mode发送不同请求
      if ( mode.value === 0 ) {
        addQuestion();
      }
      if ( mode.value === 1 ) {
        imageUnderStandChat();
      }
      if ( mode.value === 2 ) {
        drawPic();
      }
      // 角色扮演模式
      if ( mode.value === 3 ) {
        characterSimulationChat();
      }
      // 文档问答模式
      if ( mode.value === 4 ) {
        fileUnderstandChat();
      }
    }
    // 处理dialog下切换tab栏事件
    function handleTabClick(index) {
      dialogTab.value = index;
    }
    // 切换至角色模拟模式
    function changeToCharacterSimulation() {
      mode.value = 3;
      dialogTableVisible.value = true;
    }
    // 获取文件base64链接 注意！！！ 图片别上传太大的
    function getFileLink(file) {
      nowFileLinkUID.value = file.data;
      console.log(nowFileLinkUID.value)
      getBase64LinkByUID(file.data).then(res => {
        let uploadPicBase64Link = res.data;
        chatContent.push({
          user: "user",
          content: `<div><img src="data:image/png;base64,${uploadPicBase64Link}" alt="" style="width: 100%;height: 100%"/></div>`,
          time: new Date().toString()
        })
        setScrollToBottom();
        showUploadSuccess()
      })
    }
    function getFileId(file) {
      nowFileId.value = file.data;
      showUploadSuccess()
    }
    // 将md转化为html
    function mdToHtml(content,callback) {
      import('markdown-it').then(module => {
        const md = module.default('commonmark', {
          highlight: function (str, lang) {
            if (lang && hljs.getLanguage(lang)) {
              try {
                return '<pre class="hljs"><code>' +
                    hljs.highlight(lang, str, true).value +
                    '</code></pre>';
              } catch (__) {}
            }

            return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
          }
        });
        callback(md.render(content));
      });
    }
    function addLoadingToAnswer() {
      // 获取ai的所有回答 对最后一个回答进行处理
      let aiAnswerMasks = document.querySelectorAll('.chat-box-content-mask')
      let lastAiAnswerMask = aiAnswerMasks[aiAnswerMasks.length - 1];
      loading.value = ElLoading.service({
        text: "",
        spinner: "",
        target: lastAiAnswerMask,
      })
    }
    function dealAnswer(data,answer) {
      let sseData = data;
      sseData = sseData.replaceAll("&#32;", " ").replaceAll("&#92n", "\n")
      // 当机器人回答时 设置ai回答状态为加载完成
      nextTick(() => {
        // Loading should be closed asynchronously
        loading.value.close()
      })
      answer += sseData;
      return answer;
    }
    function showFileName(file) {
      chatContent.push({
        user: "user",
        content: file.name,
        time: new Date().toString()
      })
    }
    // 文件上传时显示正在上传
    function showUploading() {
      loadingMessage = ElNotification({
        message: '文件正在上传中，请稍等.',
        type: 'warning',
        icon: 'Loading',
        duration: 0
      })
    }
    // 文件上传成功时显示成功
    function showUploadSuccess() {
      loadingMessage.close()
      ElNotification({
        message: '文件上传成功!',
        type: 'success',
        duration: 2000
      })
    }
    // 对话框轮播播放
    function sayWord() {
      nextTick(() => {
        const text = document.querySelector('.text');
        const txt = talkTitle

        var index = 0;
        var xiaBiao = 0;
        var huan = true;

        setInterval(function () {

          if (huan) {
            if (index >= 9) {
              text.innerHTML = txt[xiaBiao].slice(0,9) + '<font color="#6495ed">' + txt[xiaBiao].slice(9, ++index) + '</font>';
            } else {
              text.innerHTML = txt[xiaBiao].slice(0, ++index);
            }
          } else {
            if (index >= 9) {
              text.innerHTML = txt[xiaBiao].slice(0,9) + '<font color="#6495ed">' + txt[xiaBiao].slice(9, index--) + '</font>';
            } else {
              text.innerHTML = txt[xiaBiao].slice(0, index--);
            }
          }

          if (index == txt[xiaBiao].length + 3) {
            huan = false;
          } else if (index < 0) {
            index = 0;
            huan = true;
            xiaBiao++;
            if (xiaBiao >= txt.length) {
              xiaBiao = 0;
            }
          }

        }, 200)
      })
    }
    async function eventSourceTalkWithAi(src) {
      let aiAnswer = ref('');
      chatContent.push({
        user: "ai",
        content: aiAnswer,
        time: new Date().toString()
      })
      await setScrollToBottom()
      addLoadingToAnswer();
      // fetch请求方法控制器
      let answer = '';
      let nowHtml = '';
      setInterval(async () => {
        if ( nowHtml.length > aiAnswer.value.length ) {
          let nowLen = aiAnswer.value.length;
          if ( nowHtml[nowLen] === '<' ) {
            while ( nowHtml[nowLen] !== '>' ) {
              nowLen ++;
            }
          }
          aiAnswer.value = nowHtml.slice(0,nowLen+1);
          await setScrollToBottom()
        }
      },70);
      const controller = new AbortController()
      await fetchEventSource(src, {
        method: 'GET',
        headers: {
          'content-type': 'application/json',
          'token': localStorage.getItem("token")
        },
        signal: controller.signal,
        openWhenHidden: true,
        onmessage(event) {
          answer = dealAnswer(event.data, answer)
          if (event.data === '&#92n[DONE]') {
            // 发送完成结束对话 删除打字机定时器
            controller.abort();
            return;
          }
          mdToHtml(answer, (html) => {
            nowHtml = html;
          })
          setScrollToBottom()
        },
        onclose(event) {
          controller.abort();
        },
        onerror(event) {
          ElMessage.error("对话失败，请重试");
          controller.abort();
        }
      });
      userQuestion.value = '';
    }
    // 进入页面时直接调用
    sayWord();
    /*-----------请求方法----------------*/
    // 用户进入页面时 需要清空和ai对话的历史记录
    clearChatHistory();
    // 常规对话模式
    async function addQuestion() {
      await eventSourceTalkWithAi("/api/aiChat/chat?question=" + userQuestion.value)
    }
    // 图片理解对话
    async function imageUnderStandChat() {
      await eventSourceTalkWithAi("/api/aiChat/imageUnderStandChat?question="+userQuestion.value + "&UID="+nowFileLinkUID.value)
    }
    // 角色扮演对话模式
    async function characterSimulationChat() {
      await eventSourceTalkWithAi("/api/aiChat/characterSimulationChat?question="+userQuestion.value + "&playerId=" + nowPlayer.value.playerId + "&agentId=" + nowAgent.value.agentId)
    }
    async function fileUnderstandChat() {
      await eventSourceTalkWithAi("/api/aiChat/fillUnderStandChat?question="+userQuestion.value + "&fileId=" + nowFileId.value)
    }
    function drawPic() {
      let userAskQuestion = userQuestion.value;
      chatContent.push({
        user: "ai",
        content: `好的，请稍等`,
        time: new Date().toString()
      })
      getAiDrawPic(userAskQuestion,1024,1024).then(response=> {
        console.log(response.data)
        chatContent.push({
          user: "ai",
          content: `<div><img src="data:image/png;base64,${response.data}" alt="" style="width: 100%;height: 100%"/></div>`,
          time: new Date().toString()
        })
        setScrollToBottom()
      }).catch(error=> {
        console.log(error)
      })
      userQuestion.value = ''
    }
    // 创建玩家
    function createPlayer() {
      playerForm.senderIdentity = playerForm.playerName;
      selectPlayer(playerForm.playerName).then(response=> {
        if ( response.data === 'false' ) {
          // 为true 说明可以创建
          savePlayer(playerForm).then(response=> {
            ElNotification({
              title: '成功',
              message: '创建成功',
              type: 'success',
            })
            // 初始化playerForm
            playerForm.playerName = '';
            playerForm.playerType = '';
            playerForm.description = '';
            playerForm.senderIdentity = '';
          })
        }
      }).catch(error=> {
        console.log(error);
      })
    }
    // 创建人格
    function createAgent() {
      agentForm.playerId = nowPlayer.value.playerId;
      saveAgent(agentForm).then(response => {
        ElNotification({
          title: '成功',
          message: '创建成功',
          type: 'success',
        })
        // 初始化agentForm
        agentForm.playerId = '';
        agentForm.agentName = '';
        agentForm.description = '';
        agentForm.agentType = '';
        agentForm.agentSenderIdentity = '';
        agentForm.identity = '';
        agentForm.personalityDescription = '';
        agentForm.hobby = '';
        agentForm.keyPersonality = '';
        agentForm.mission = '';
      })
    }
    // 获取当前用户的玩家信息 并以最后一个作为默认的玩家
    function getNowPlayer() {
      getPlayerInfoList().then(response => {
        playerList.value = response.data;
        nowPlayer.value = response.data[0];
      })
    }
    // 获取当前玩家创建的人格的信息
    function getPlayerAgentInfo() {
      getAgentInfo(nowPlayer.value.playerId).then(response => {
        nowAgent.value = response.data;
      })
    }
    // 生成短期记忆
    function generateShortMemory() {
      languageSceneForm.value.agentId = nowAgent.value.agentId;
      languageSceneForm.value.playerInvolved = nowPlayer.value.playerId;
      languageSceneForm.value.agentInvolved = nowAgent.value.agentId;
      generateMemory(languageSceneForm.value).then(response => {
        ElNotification({
          title: '成功',
          message: '创建成功',
          type: 'success',
        })
        // 初始化languageSceneForm
        languageSceneForm.value.example = '';
        languageSceneForm.value.description = '';
      })
    }
    /*-----------钩子函数----------------*/
    watch(mode, (newMode, oldMode) => {
      if (newMode === 0) {
        modeText.value = "聊天模式"
      } else if (newMode === 1) {
        modeText.value = "图片理解模式"
      }else if (newMode === 2) {
        modeText.value = "图片生成模式"
      }else if (newMode === 3) {
        modeText.value = '角色扮演模式'
      }else if (newMode === 4) {
        modeText.value = '文档问答模式'
      }
    })
    window.onload = function () {
      let times = null;
      const micArea = document.querySelector('.mic-area');
      const xfVoice = new XfVoiceDictation({

        // 服务接口认证信息 注：APISecret 和 APIKey 的长度都差不多，请要填错哦，！
        APPID: '3c591f62',
        APISecret: 'Y2M2YWU0N2QzOGE0ODcyMmY3ODgzMWY2',
        APIKey: '14a25fc24a288e7c358a0e795275aa57',
        // 注：要获取以上3个参数，请到迅飞开放平台：https://www.xfyun.cn/services/voicedictation 【注：这是我的迅飞语音听写（流式版）每天服务量500（也就是调500次），如果你需求里大请购买服务量：https://www.xfyun.cn/services/voicedictation?target=price】

        // webSocket请求地址 非必传参数，默认为：wss://iat-api.xfyun.cn/v2/iat
        // url: '',


        onWillStatusChange: function (oldStatus, newStatus) {
          //可以在这里进行页面中一些交互逻辑处理：注：倒计时（语音听写只有60s）,录音的动画，按钮交互等！
        },
        onTextChange: function (text) {
          //监听识别结果的变化
          userQuestion.value = text;

          // 3秒钟内没有说话，就自动关闭
          if (text) {
            clearTimeout(times);
            times = setTimeout(() => {
              this.stop(); // xfVoice.stop();
              micArea.style.opacity = 0;
            }, 3000);
          };
        }
      });
      const voiceBtn = document.getElementById('voiceBtn');
      voiceBtn['onmousedown'] = function() {
        xfVoice.start();
        micArea.style.opacity = 1;
      }

      voiceBtn['onmouseup'] = function() {
        xfVoice.stop();
        micArea.style.opacity = 0;
      }
    }
    return {
      nowAgent,
      playerList,
      nowPlayer,
      playerForm,
      dialogTableVisible,
      dialogTab,
      mode,
      modeText,
      userQuestion,
      scrollbarRef,
      innerRef,
      chatContent,
      languageSceneForm,
      agentForm,
      talkTitle,
      getResult,
      getPlayerAgentInfo,
      getNowPlayer,
      changeToCharacterSimulation,
      handleTabClick,
      createPlayer,
      createAgent,
      generateShortMemory,
      getFileLink,
      getFileId,
      showUploading,
      showFileName,
    }
  }


}
</script>

<template>
  <div class="common-layout">
    <el-container>
      <el-header class="header-outer">
        <Header></Header>
      </el-header>
      <el-main>
        <el-card class="chat-card">
          <el-row :gutter="24" style="width: 100%;height: 100%">
            <el-col :span="6">
              <el-card class="chat-card-left">
                <div class="new-chat-box">
                  <h4>新的对话</h4>
                </div>
              </el-card>
            </el-col>
            <el-col :span="18">
              <el-card class="chat-card-right">
                <div class="chat-card-right-header">
                  <span class="text" style="font-size: 22px;font-weight: bold"></span>
                  <div>共 {{chatContent.length}} 条对话</div>
                </div>
                <div class="chat-card-right-body">
                  <div class="mic-area">
                    <img src="../../../assets/image/voice.gif" alt="" style="width: 100%;height: 100%">
                  </div>
                  <el-scrollbar ref="scrollbarRef" always>
                    <div ref="innerRef">
                      <div v-for="(item,index) in chatContent" :key="index">
                        <div v-if="item.user === 'user'" class="user-chat-box">
                          <div class="chat-box-content">
                            <div class="chat-box-content-header">
                              <div class="chat-box-content-avatar">
                                <div class="user-avatar">
                                  <img src="https://cdn.staticfile.org/emoji-datasource-apple/14.0.0/img/apple/64/1f603.png" alt="" style="font-size: 18px; height: 18px; width: 18px;" loading="eager">
                                </div>
                              </div>
                            </div>
                            <div class="chat-box-content-item">
                              <div class="markdown-body" dir="auto" style="font-size: 14px;">
                                <p dir="auto" v-html="item.content"></p>
                              </div>
                            </div>
                            <div class="chat-box-content-action-date">{{item.time}}</div>
                          </div>
                        </div>
                        <div v-else class="ai-chat-box">
                          <div class="chat-box-content">
                            <div class="chat-box-content-header">
                              <div class="chat-box-content-avatar">
                                <div class="user-avatar">
                                  <img xmlns src="../../../assets/icon/gpt.png" alt="" style="font-size: 18px; height: 18px; width: 18px;" loading="eager">
                                </div>
                              </div>
                            </div>
                            <div class="chat-box-content-item">
                              <div class="chat-box-content-mask"></div>
                              <div class="markdown-body" dir="auto" style="font-size: 14px;" v-if="item.content">
                                <span v-html="item.content"></span>
                              </div>
                            </div>
                            <div class="chat-box-content-action-date" v-if="item.content">{{item.time}}</div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </el-scrollbar>
                </div>
                <div class="chat-card-right-bottom">
                  <div class="chat-card-right-bottom-actions">
                    <el-tag type="success">当前模式：{{modeText}}</el-tag>
                    <el-popover
                        placement="top-start"
                        title="聊天模式"
                        :width="200"
                        trigger="hover"
                        content="与Ai畅聊。"
                    >
                      <template #reference>
                        <el-button class="chat-card-right-bottom-button" :icon="ChatDotRound" @click="mode = 0" style="margin-left: 5px"></el-button>
                      </template>
                    </el-popover>
                    <el-popover
                        placement="top-start"
                        title="图片理解"
                        :width="200"
                        trigger="hover"
                        content="与Ai聊天时，不妨与Ai通过发送图片来增加趣味性吧。"
                    >
                      <template #reference>
                        <el-upload
                            ref="uploadRef"
                            class="upload-demo"
                            action="/api/aiChat/getBase64Link"
                            :show-file-list="false"
                            :on-success="getFileLink"
                            :on-progress="showUploading"
                        >
                          <template #trigger>
                            <el-button class="chat-card-right-bottom-button" :icon="Upload" style="margin-left: 5px;" @click="mode = 1"></el-button>
                          </template>
                        </el-upload>
                      </template>
                    </el-popover>
                    <el-popover
                        placement="top-start"
                        title="图片生成"
                        :width="200"
                        trigger="hover"
                        content="点击切换至图片生成模式。"
                    >
                      <template #reference>
                        <el-button class="chat-card-right-bottom-button" :icon="Picture" @click="mode = 2" style="margin-left: 5px"></el-button>
                      </template>
                    </el-popover>
                    <el-popover
                        placement="top-start"
                        title="角色模拟"
                        :width="200"
                        trigger="hover"
                    >
                      与Ai来一场角色扮演游戏。
                      <el-dialog v-model="dialogTableVisible" title="角色模拟控制面板" width="1000">
                        <div>
                          <el-container>
                            <el-aside width="200px">
                              <el-menu
                                  default-active="0"
                                  class="el-menu-vertical-demo"
                                  @select="handleTabClick"
                              >
                                <el-menu-item index="0">
                                  <el-icon><Place /></el-icon>
                                  <span>创建玩家</span>
                                </el-menu-item>
                                <el-menu-item index="1" @click="getNowPlayer">
                                  <el-icon><Document /></el-icon>
                                  <span>玩家信息</span>
                                </el-menu-item>
                                <el-menu-item index="2">
                                  <el-icon><Coordinate /></el-icon>
                                  <span>创建人格</span>
                                </el-menu-item>
                                <el-menu-item index="3" @click="getPlayerAgentInfo">
                                  <el-icon><Notebook /></el-icon>
                                  <span>人格管理</span>
                                </el-menu-item>
                                <el-menu-item index="4">
                                  <el-icon><DocumentAdd /></el-icon>
                                  <span>添加记忆</span>
                                </el-menu-item>
                              </el-menu>
                            </el-aside>
                            <el-main>
                              <div v-if="dialogTab === '0'">
                                <el-form :model="playerForm" label-width="auto" style="max-width: 600px">
                                  <el-form-item label="玩家名称">
                                    <el-input v-model="playerForm.playerName" />
                                  </el-form-item>
                                  <el-form-item label="玩家类型">
                                    <el-radio-group v-model="playerForm.playerType">
                                      <el-radio label="网页端注册玩家" value="网页端注册玩家"></el-radio>
                                    </el-radio-group>
                                  </el-form-item>
                                  <el-form-item label="玩家描述">
                                    <el-input v-model="playerForm.description" type="textarea" />
                                  </el-form-item>
                                  <el-form-item>
                                    <el-button type="primary" @click="createPlayer">创建</el-button>
                                    <el-button>取消</el-button>
                                  </el-form-item>
                                </el-form>
                              </div>
                              <div v-else-if="dialogTab === '1'">
                                <el-descriptions
                                    class="margin-top"
                                    title="当前启用玩家信息如下"
                                    :column="3"
                                    :size="'default'"
                                    border
                                >
                                  <template #extra>
                                    <el-button type="primary" size="small">启用</el-button>
                                    <el-button type="primary" size="small">编辑</el-button>
                                    <el-button type="primary" size="small">注销</el-button>
                                  </template>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon :style="iconStyle">
                                          <user />
                                        </el-icon>
                                        名称
                                      </div>
                                    </template>
                                    {{nowPlayer.playerName}}
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <iphone />
                                        </el-icon>
                                        类型
                                      </div>
                                    </template>
                                    <el-tag size="small">{{nowPlayer.playerType}}</el-tag>
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <tickets />
                                        </el-icon>
                                        身份标识
                                      </div>
                                    </template>
                                    <el-tag size="small">{{nowPlayer.senderIdentity}}</el-tag>
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <office-building />
                                        </el-icon>
                                        描述
                                      </div>
                                    </template>
                                    {{nowPlayer.description}}
                                  </el-descriptions-item>
                                </el-descriptions>
                              </div>
                              <div v-else-if="dialogTab === '2'">
                                <el-form :model="agentForm" label-width="auto" style="max-width: 600px">
                                  <el-form-item label="人格名称">
                                    <el-input v-model="agentForm.agentName" />
                                  </el-form-item>
                                  <el-form-item label="人格类型">
                                    <el-radio-group v-model="agentForm.agentType">
                                      <el-radio label="示例人格" value="示例人格"></el-radio>
                                    </el-radio-group>
                                  </el-form-item>
                                  <el-form-item label="社会身份">
                                    <el-input v-model="agentForm.identity" />
                                  </el-form-item>
                                  <el-form-item label="性格描述">
                                    <el-input v-model="agentForm.description" type="textarea" />
                                  </el-form-item>
                                  <el-form-item label="爱好">
                                    <el-input v-model="agentForm.hobby"/>
                                  </el-form-item>
                                  <el-form-item label="性格关键词">
                                    <el-input v-model="agentForm.keyPersonality"/>
                                  </el-form-item>
                                  <el-form-item label="任务目标">
                                    <el-input v-model="agentForm.mission"/>
                                  </el-form-item>
                                  <el-form-item>
                                    <el-button type="primary" @click="createAgent">创建</el-button>
                                    <el-button>取消</el-button>
                                  </el-form-item>
                                </el-form>
                              </div>
                              <div v-else-if="dialogTab === '3'">
                                <el-descriptions
                                    class="margin-top"
                                    title="当前启用人格信息如下"
                                    :column="3"
                                    :size="'default'"
                                    border
                                >
                                  <template #extra>
                                    <el-button type="primary" size="small">编辑</el-button>
                                    <el-button type="primary" size="small">注销</el-button>
                                  </template>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <user />
                                        </el-icon>
                                        人格名称
                                      </div>
                                    </template>
                                    {{nowAgent.agentName}}
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <iphone />
                                        </el-icon>
                                        类型
                                      </div>
                                    </template>
                                    <el-tag size="small">{{nowAgent.agentType}}</el-tag>
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <tickets />
                                        </el-icon>
                                        身份标识
                                      </div>
                                    </template>
                                    <el-tag size="small">{{nowAgent.identity}}</el-tag>
                                  </el-descriptions-item>
                                  <el-descriptions-item>
                                    <template #label>
                                      <div class="cell-item">
                                        <el-icon>
                                          <office-building />
                                        </el-icon>
                                        描述
                                      </div>
                                    </template>
                                    {{nowAgent.description}}
                                  </el-descriptions-item>
                                </el-descriptions>
                              </div>
                              <div v-else-if="dialogTab === '4'">
                                <el-form :model="languageSceneForm" label-width="auto" style="max-width: 600px">
                                  <el-form-item label="场景">
                                    <el-input resize='none' :autosize="{ minRows: 3, maxRows: 5 }" v-model="languageSceneForm.example" type="textarea" placeholder="这里描述当前人格正处于哪种场景下。" />
                                  </el-form-item>
                                  <el-form-item label="例句">
                                    <el-input resize='none' :autosize="{ minRows: 3, maxRows: 5 }" v-model="languageSceneForm.description" type="textarea" placeholder="这里填写当前人格在给定场景下可能说的话。" />
                                  </el-form-item>
                                  <el-form-item>
                                    <el-button type="primary" @click="generateShortMemory">创建</el-button>
                                    <el-button>取消</el-button>
                                  </el-form-item>
                                </el-form>
                              </div>
                            </el-main>
                          </el-container>
                        </div>
                      </el-dialog>
                      <template #reference>
                        <el-button class="chat-card-right-bottom-button" :icon="User" @click="changeToCharacterSimulation" style="margin-left: 5px"></el-button>
                      </template>
                    </el-popover>
                    <el-popover
                        placement="top-start"
                        title="文档问答"
                        :width="200"
                        trigger="hover"
                        content="论文不会翻译？文档看不懂？文档太多不会总结？统统交给AI吧！。"
                    >
                      <template #reference>
                        <el-upload
                            ref="uploadRef"
                            class="upload-demo"
                            action="/api/aiChat/fileUnderStandUpload"
                            :show-file-list="false"
                            :on-success="getFileId"
                            :on-progress="showUploading"
                            :before-upload="showFileName"
                        >
                          <template #trigger>
                            <el-button class="chat-card-right-bottom-button" :icon="DocumentCopy" style="margin-left: 5px;" @click="mode = 4"></el-button>
                          </template>
                        </el-upload>
                      </template>
                    </el-popover>
                    <el-tag style="position: absolute;right: 2%;">Tips: 如果ai回答时未能将公式渲染，可前往<i><strong>工具栏->图片转公式</strong></i>手动进行渲染</el-tag>
                  </div>
                  <div class="chat-card-right-bottom-input">
                    <el-input v-model="userQuestion" class="chat-card-right-bottom-textarea" placeholder="请输入您要询问的内容，使用Enter键或点击发送按钮开启Ai对话之旅" rows="3" style="font-size: 14px;" @keydown.enter="getResult"></el-input>
                    <el-button class="chat-card-right-bottom-textarea-button" :icon="Mic" style="right: 110px;width: 110px;background-color: #67C23A;" id="voiceBtn">长按语音输入</el-button>
                    <el-button class="chat-card-right-bottom-textarea-button" @click="getResult" :icon="Position">发送</el-button>
                  </div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </el-card>
      </el-main>
    </el-container>
  </div>
</template>

<style lang="less" scoped>
@keyframes chat_slide-in__nvZgA {
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}
.common-layout {
  background: -moz-linear-gradient(to bottom, #f3f5f8, #fff);
  background: linear-gradient(to bottom, #f3f5f8, #fff);
  .header-outer {
    height: 100%;
    // 改变盒子背景 略灰一点
    background-color: #fff;
    // 改变外部盒子边界线便于区分
    border-bottom: 2px solid #eee;
    // 设置盒子底部阴影
    box-shadow: 0 2px 8px 0 rgba(7, 17, 27, 0.06);
  }

  .chat-card {
    width: 1300px;
    height: 100%;
    margin: 0 auto;
    position: relative;
    border: 1px solid #dedede;
    border-radius: 20px;
    box-shadow: 50px 50px 100px 10px rgba(0,0,0,.1);
    color: #303030;
    background-color: #fff;
    display: flex;
    overflow: hidden;
    box-sizing: border-box;
    .chat-card-left {
      top: 0;
      width: 300px;
      height: 850px;
      padding: 20px;
      box-sizing: border-box;
      background-color: #e7f8ff;
      display: flex;
      flex-direction: column;
      box-shadow: inset -2px 0 2px 0 rgba(0, 0, 0, .05);
      position: relative;
      transition: width .05s ease;

      .new-chat-box {
        width: 100%;
        height: 50%;
        margin: 5px auto;
        background-color: #fff;
        border-radius: 10px;
        box-shadow: 0 2px 4px 0 rgba(0,0,0,.05);
        transition: background-color .3s ease;
        cursor: pointer;
        border: 1px solid #52cc5c;
        position: relative;
        content-visibility: auto;
        display: flex;
        align-items: center;
        h4 {
          margin-left: 10px;
        }
      }
    }
    .chat-card-right {
      width: 1000px;
      margin-left: -25px;
      display: flex;
      flex-direction: column;
      position: relative;
      height: 100%;
      .chat-card-right-header {
        height: 60px;
        padding: 14px 20px;
        border-bottom: 1px solid rgba(0, 0, 0, .1);
        position: relative;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
      .chat-card-right-body {
        flex: 1 1;
        overflow: auto;
        overflow-x: hidden;
        padding: 20px 20px 40px;
        position: relative;
        overscroll-behavior: none;
        height: 570px;
        // 长按语音输入出现的麦克风框
        .mic-area {
          opacity: 0;
          width: 200px;
          height: 200px;
          position: absolute;
          top: 30%;
          left: 40%;
          transition-property: all;
          transition-timing-function: cubic-bezier(.4, 0, .2, 1);
          transition-duration: 1s;
          border-radius: 12px;
          backdrop-filter: blur(20px) saturate(180%);
          background-color: hsl(0 0% 100% / .8);
          z-index: 1;
          box-sizing: border-box;
          overflow: visible;
          --un-shadow: 0 20px 15px 10px rgb(0 0 0 / .14), 0 8px 10px -6px rgb(0 0 0 / .12);
          box-shadow: 0 0 rgb(0 0 0 / 0), 0 0 rgb(0 0 0 / 0), var(--un-shadow);
        }
        .user-chat-box {
          display: flex;
          flex-direction: row-reverse;
        }
        // ai回复框的样式
        .ai-chat-box {
          display: flex;
          flex-direction: row;
        }
        .user-chat-box,.ai-chat-box {
          .chat-box-content {
            max-width: 80%;
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            .chat-box-content-header {
              flex-direction: row-reverse;
              margin-top: 20px;
              display: flex;
              align-items: center;

              .chat-box-content-avatar {
                position: relative;

                .user-avatar {
                  height: 30px;
                  min-height: 30px;
                  width: 30px;
                  min-width: 30px;
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  border: 1px solid #dedede;
                  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, .05);
                  border-radius: 11px;
                }
              }
            }

            .chat-box-content-item {
              box-sizing: border-box;
              max-width: 100%;
              margin-top: 10px;
              border-radius: 10px;
              background-color: rgba(0,0,0,.05);
              padding: 10px;
              font-size: 14px;
              -webkit-user-select: text;
              -moz-user-select: text;
              user-select: text;
              word-break: break-word;
              border: 1px solid #dedede;
              position: relative;
              transition: all .3s ease;
              .chat-box-content-mask {
                position: absolute;
                height: 100px;
                width: 200px;
                left: 0;
                top: 0;
                :deep(.el-loading-spinner) {
                  /* 图片替换为你自定义的即可 */
                  background: url('../../../assets/icon/gptLoading.gif') no-repeat;
                  background-size: 100px 100px;
                  width: 100%;
                  height: 100%;
                  position: relative;
                  top: 0;
                  left: 0;
                }
                :deep(.el-loading-spinner .circular) {
                  width: 0px;
                  height: 0px;
                  animation: loading-rotate 2s linear infinite;
                  display: none;
                }
              }
              .markdown-body {
                -ms-text-size-adjust: 100%;
                -webkit-text-size-adjust: 100%;
                margin: 0;
                color: #24292f;
                background-color: transparent;
                font-size: 14px;
                line-height: 1.5;
                word-wrap: break-word;
              }

              .markdown-body:after, .markdown-body:before {
                display: table;
                content: "";
              }

              .markdown-body:after {
                clear: both;
              }
            }

            .chat-box-content-action-date {
              font-size: 12px;
              opacity: .2;
              white-space: nowrap;
              transition: all .6s ease;
              color: #303030;
              text-align: right;
              width: 100%;
              box-sizing: border-box;
              padding-right: 10px;
              pointer-events: none;
              z-index: 1;
            }
          }
        }
        .user-chat-box > .chat-box-content {
          align-items: flex-end;
        }
        .user-chat-box > .chat-box-content > .chat-box-content-header {
          flex-direction: row-reverse;
        }
        .user-chat-box > .chat-box-content > .chat-box-content-item {
          background-color: #e7f8ff;
        }
      }
      .chat-card-right-bottom {
        position: relative;
        width: 100%;
        padding: 10px 20px 20px;
        box-sizing: border-box;
        flex-direction: column;
        border-top: 1px solid #dedede;
        box-shadow: 0px 2px 4px 0px rgba(0,0,0,.05);
        .chat-card-right-bottom-actions {
          display: flex;
          flex-wrap: wrap;
          .chat-card-right-bottom-button {
            display: inline-flex;
            border-radius: 20px;
            font-size: 12px;
            background-color: #fff;
            color: #303030;
            border: 1px solid #dedede;
            padding: 4px 10px;
            animation: chat_slide-in__nvZgA .3s ease;
            box-shadow: 0px 2px 4px 0px rgba(0,0,0,.05);
            transition: width .3s ease;
            align-items: center;
            height: 25px;
            width: 30px;
            overflow: hidden;
          }
          .file-upload {
            display: none; // 设置上传文件的input隐藏
          }
        }
        .chat-card-right-bottom-input {
          margin-top: 5px;
          display: flex;
          flex: 1 1;
          padding: 0;
          .chat-card-right-bottom-textarea {
            height: 100%;
            width: 100%;
            border-radius: 10px;
            border: 1px solid #dedede;
            box-shadow: 0 -2px 5px rgba(0, 0, 0, .03);
            background-color: #fff;
            color: #303030;
            font-family: inherit;
            resize: none;
            outline: none;
            box-sizing: border-box;
            min-height: 68px;
          }
          .chat-card-right-bottom-textarea-button {
            background-color: #1d93ab;
            color: #fff;
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 10px;
            cursor: pointer;
            transition: all .3s ease;
            overflow: hidden;
            -webkit-user-select: none;
            -moz-user-select: none;
            user-select: none;
            outline: none;
            border: none;
            position: absolute;
            right: 25px;
            bottom: 25px;
            width: 70px;
          }
        }
      }
    }
  }
}

.common-layout /deep/ .el-card__body {
  padding: 0;
}
</style>